package cn.s1995.sloth.bizs.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.s1995.sloth.bizs.constant.BizCst;
import cn.s1995.sloth.bizs.constant.CacheNames;
import cn.s1995.sloth.bizs.constant.TimeCst;
import cn.s1995.sloth.common.core.constant.enums.hint.Hint;
import cn.s1995.sloth.bizs.entity.UserLike;
import cn.s1995.sloth.bizs.entity.Video;
import cn.s1995.sloth.bizs.entity.VideoComment;
import cn.s1995.sloth.bizs.enums.NotifyTemplateEnum;
import cn.s1995.sloth.bizs.mapper.VideoCommentMapper;
import cn.s1995.sloth.bizs.oo.req.VideoCommentREQ;
import cn.s1995.sloth.bizs.oo.vo.VideoCommentVO;
import cn.s1995.sloth.bizs.service.MessageService;
import cn.s1995.sloth.bizs.service.UserLikeService;
import cn.s1995.sloth.bizs.service.VideoCommentService;
import cn.s1995.sloth.bizs.service.VideoService;
import cn.s1995.sloth.common.core.util.R;
import cn.s1995.sloth.common.core.util.SpringContextHolder;
import cn.s1995.sloth.common.security.service.SlothUser;
import cn.s1995.sloth.common.security.util.SecurityUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 视频评论
 *
 * @author Sasshi
 * @date 2023-12-13 10:30:37
 */
@Service
public class VideoCommentServiceImpl extends ServiceImpl<VideoCommentMapper, VideoComment> implements VideoCommentService {

	@Resource
	private VideoService videoService;
	@Resource
	private UserLikeService userLikeService;
	@Resource
	private MessageService messageService;


	@Override
	public Page getCommentPage(Page page, VideoCommentREQ req) {
//		MPJLambdaWrapper<VideoComment> wrapper = new MPJLambdaWrapper<VideoComment>()
//	            .selectAll(VideoComment.class)
//	            .selectAs("a", AppUser::getNickname, VideoCommentVO::getUserNickname)
//	            .selectAs("b", AppUser::getNickname, VideoCommentVO::getToUserNickname)
//	            .selectAs(AppUser::getAvatar, VideoCommentVO::getUserAvatar)
//	            .select("count(c.id) as childCommentCount")
//	            .leftJoin("`biz_video_comment` c on c.pid = t.id")
//	            .leftJoin(AppUser.class, "a", AppUser::getUserId, VideoComment::getUid)
//	            .leftJoin(AppUser.class, "b", AppUser::getUserId, VideoComment::getToUserId)
//	            .eq(ObjectUtil.isNotNull(req.getPid()), VideoComment::getPid, req.getPid())
//	            .eq(ObjectUtil.isNotNull(req.getVideoId()), VideoComment::getVideoId, req.getVideoId())
//	            .eq(VideoComment::getState, BizCst.CommonAuditState.approve)
//	            .groupBy(VideoComment::getId)
//	            .orderByDesc(VideoComment::getCreateTime);
//		return baseMapper.selectJoinPage(page, VideoCommentVO.class, wrapper);
		return baseMapper.selectCommentPage(page, req);

	}

	@Override
	public void add(VideoCommentREQ req) {
		Video video = videoService.getById(req.getVideoId());
		if(ObjectUtil.isNotNull(video)) {
			VideoComment videoComment = BeanUtil.copyProperties(req, VideoComment.class);
			SlothUser user = SecurityUtils.getUser();
			videoComment.setUid(user.getId());
			//现在默认通过，不用审核
			videoComment.setState(BizCst.CommonAuditState.approve);
			videoComment.setLikeCount(0);
			if(ObjectUtil.isNotNull(req.getPid()) && req.getPid() != 0) {
				//非一级评论
				VideoComment toComment = this.getById(req.getPid());
				if(ObjectUtil.isNotNull(toComment)) {
					videoComment.setToId(req.getPid());
					if(toComment.getPid() == 0) {
						videoComment.setPid(toComment.getId());
					}else {
						videoComment.setPid(toComment.getPid());
						videoComment.setToUserId(toComment.getUid());
					}
					//发送消息
					if(ObjectUtil.isNotNull(toComment)) {
				        messageService.sendMsg(
				        		NotifyTemplateEnum.system_received_comment.getId(),
				    			0L,
				    			toComment.getUid(),
				    			BizCst.Message.Type.system,
				    			BizCst.Message.BindType.videoComment,
				    			videoComment.getId(),
				    			user.getNickname(),
				    			videoComment.getContent());
					}
					this.save(videoComment);
				}
			}else {
				//一级评论
				videoComment.setPid(0L);
				videoComment.setToId(0L);
				//对视频的评论
				if(ObjectUtil.isNotNull(video.getUid())){
			        messageService.sendMsg(
			        		NotifyTemplateEnum.system_received_comment.getId(),
			    			0L,
			    			video.getUid(),
			    			BizCst.Message.Type.system,
			    			BizCst.Message.BindType.videoComment,
			    			videoComment.getId(),
			    			user.getNickname(),
			    			videoComment.getContent());
				}
				this.save(videoComment);
			}
			//更新缓存
			Video cache = videoService.updateCache(videoComment.getVideoId(), 1, 11);
			if(Duration.between(cache.getUpdateTime(), LocalDateTime.now()).toSeconds() > TimeCst.TIME_ONE_HOUR)
				videoService.syncCacheToDB(videoComment.getVideoId());
		}
	}

	@Override
	public void setLikeStatus(Long uid, VideoCommentVO vo) {
		VideoCommentService videoCommentService = SpringContextHolder.getBean(VideoCommentService.class);
		Set<Long> likeUserSet = videoCommentService.getLikeUserSet(vo.getId());
		if(likeUserSet.contains(uid))
			vo.setLike(true);
	}

	@Override
	@Cacheable(value = CacheNames.videoCommentLike, key= "#id")
	public Set<Long> getLikeUserSet(Long id) {
		List<UserLike> list = userLikeService.list(
					Wrappers.lambdaQuery(UserLike.class)
							.eq(UserLike::getType, BizCst.UserLike.Type.videoComment)
							.eq(UserLike::getBindId, id)
				);
		if(ObjectUtil.isNotEmpty(list))
			return list.stream()
					.map(e -> e.getUid())
					.collect(Collectors.toSet());
		return new HashSet<Long>();
	}

	@Override
	public R like(Long id) {
		VideoCommentService videoCommentService = SpringContextHolder.getBean(VideoCommentService.class);
		VideoComment videoComment = this.getById(id);
		if(ObjectUtil.isNull(videoComment))
			return R.failed(Hint.NOT_FOUND);
		//判断是否已点赞过该评论
		Long uid = SecurityUtils.getUser().getId();
		Set<Long> likeUserSet = videoCommentService.getLikeUserSet(id);
		if(likeUserSet.contains(uid)) {
			//已点赞，取消点赞，修改数量
			userLikeService.remove(
						Wrappers.lambdaQuery(UserLike.class)
								.eq(UserLike::getType, BizCst.UserLike.Type.videoComment)
								.eq(UserLike::getBindId, id)
								.eq(UserLike::getUid, uid)
					);
			this.baseMapper.updateLikeCount(id, -1);
			//更新点赞集合缓存
			likeUserSet.remove(uid);
			videoCommentService.updateLikeUserSet(id, likeUserSet);
		}else {
			//点赞
			userLikeService.save(
						UserLike.builder()
								.action(BizCst.UserLike.Action.like)
								.type(BizCst.UserLike.Type.videoComment)
								.uid(uid)
								.bindId(id)
								.build()
					);
			this.baseMapper.updateLikeCount(id, 1);
			likeUserSet.add(uid);
			videoCommentService.updateLikeUserSet(id, likeUserSet);
			//点赞视频评论发送消息
	        messageService.sendMsg(
	        		NotifyTemplateEnum.system_received_like.getId(),
	    			0L,
	    			videoComment.getUid(),
	    			BizCst.Message.Type.system,
	    			BizCst.Message.BindType.videoComment,
	    			videoComment.getId());
		}
		return R.ok();
	}

	@Override
	@CachePut(value = CacheNames.videoCommentLike, key= "#id")
	public Set<Long> updateLikeUserSet(Long id, Set<Long> set) {
		return set;
	}
}
